#lang scribble/doc
@(require scribble/manual scribble/bnf "common.rkt" (for-label racket/base))

@title[#:tag "demod"]{@exec{raco demod}: Demodularizing Programs}

@declare-exporting[compiler/demodularizer/main]

The @exec{raco demodularize} command (usually used with the shorthand
@exec{raco demod}) takes a Racket module and flattens all of its
dependencies into a single compiled module. A file
@filepath{@nonterm{name}.rkt} is demodularized into
@filepath{@nonterm{name}_rkt_merged.zo}.

The demodularized @filepath{.zo} file can be run by passing it as an
argument to the @exec{racket} command-line program, or it can be
turned into an executable with @seclink["exe"]{@exec{raco exe}}.

A large single module generated by the demodularizer may trigger size
limits in the compiler that prevent whole-module optimizations. Set
the @envvar{PLT_CS_COMPILE_LIMIT} environment variable to raise the
limit, and check @racket['info] logging at the @racket['linklet] topic
(e.g., set @envvar{PLTSTDERR} to @tt["info@linklet"]) for
information about when compilation is restricted to smaller functions.

The @exec{raco demod} command accepts these flags:

@itemlist[

 @item{@Flag{o} @nonterm{file} --- writes the flattened module to
       @nonterm{file} instead of
       @filepath{@nonterm{name}_@nonterm{ext}_merged.zo} for an input
       file @filepath{@nonterm{name}.@nonterm{ext}}.}
 
 @item{@Flag{e} @nonterm{path} or @DFlag{exclude} @nonterm{path} ---
       excludes the module in @nonterm{path} from flattening, as well
       as all of its dependencies.}

 @item{@Flag{M} or @DFlag{compile-any} --- flattens the module to
       machine-independent form, instead of recompiling the flattened
       module to the current platform and Racket virtual machine; the
       output generated with @Flag{M} loads more slowly than a
       machine-specific form, but @seclink["decompile"]{raco
       decompile} can show the flattened module in a format that is
       closer to source.}

 @item{@Flag{r} or @DFlag{recompile} --- (re)compiles the module to
        machine-dependent form after flattening; this mode is the
        default except on @BC, where flattening
        can work in terms of bytecode files.}

 @item{@DFlag{work} @nonterm{dir} --- uses @nonterm{dir} to cache
       compiled modules in an intermediate form for flattening; using
       @DFlag{work} with the same @nonterm{dir} for multiple uses of
       @exec{raco demod} can greatly speed up demodularization, and
       since the cache is based on @exec{raco make}, it works even
       with different input files or when modules to be flattened have
       changed since the last use of the cache.}

 @item{@Flag{g} or @DFlag{garbage-collect} --- aggressively prunes
       definitions that are unreferenced on the assumption that the
       right-hand side of a definition has no side effect; due to that
       unchecked assumption, this conversion may not preserve the
       behavior of the input module.}

]

@history[#:changed "1.10" @elem{Added @Flag{M}/@DFlag{compile-any},
                                @DFlag{work}, and support for Racket CS.}]
